package main

import (
	"fmt"
)

//定义一个接口
//接口是一个方法列表（方法签名），只负责定义规范不实现
//有具体的对象来实现，如果一个对象实现了接口中的所有方法列表，那么这个对象就实现了这个接口
//接口类型不用指针
type Usber interface {
	getName() string //方法签名，由方法名、接收参数、返回值
}

//定义两个usb设置类型
type phone struct {
	Name string
}

func (p *phone) getName() string {
	return p.Name
}

type computer struct {
	Brand string
}

func (p *computer) getName() string {
	return p.Brand
}

//封装一个公共方法，接收参数是usber接口类型
//因为phone和computer实现了usber接口类型，所以可以进行数据转换
//phone和computer类型 -> usber类型，这种从下往上转，是隐式转账（golang自动处理）
func transData(u Usber) string {
	name := u.getName()
	return name + " 处理后"
}

func main() {
	//实例化
	p := &phone{Name: "华为 Meta60 Pro"}
	c := &computer{Brand: "戴尔"}
	//结构体实现接口后，接口类型可以指向结构体类型，特性就是结构体特性
	//结构体实现方法后，可以进行数据转换 把p换成u
	var u Usber = p
	fmt.Println(u.getName())
	var u1 Usber = c
	fmt.Println(u1.getName())
	//数据转换，从下往上转，隐式转换
	fmt.Println(transData(p))
	fmt.Println(transData(c))
	//从上往下转，接口断言
	var u2 Usber
	u2 = &phone{Name: "苹果"}
	fmt.Printf("%T %v\n", u2, u2)
	v, ok := u2.(*phone)
	if !ok {
		fmt.Println("断言失败")
	} else {
		fmt.Println("%T %v\n", v, v)
	}

	//空接口
	//没有方法列表的接口就是空接口
	//任何类型都默认实现了空接口
	slice := []interface{}{
		"zhangsan",
		15,
		true,
		32.2,
	}
	fmt.Println(slice)
	//map实现空接口
	mapInfo := map[string]interface{}{}
	mapInfo["name"] = "zhangsan"
	mapInfo["age"] = 20
	mapInfo["married"] = false
	fmt.Println(mapInfo)
	//类型断言
	var x interface{}
	x = "beijing"
	v1, ok := x.(string)
	if ok {
		fmt.Println(v1)
	}
	//证明x是个接口类型，并不是string类型
	//strings.Replace(x, "i", "I", -1)

}
